package domein;

import java.io.IOException;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

/**
 * 
 * @author rensbonnez
 *
 */

public class FileServer extends Thread
{
	public static Logger logger = Logger.getLogger("MyLog");
	private ServerSocket socket;
	private ExecutorService fileDownloads;
	private ExecutorService fileUploads;
	private boolean serverIsRunning;
	private static final int PORT = 8500;
	
	public FileServer()
	{
		setFileDownloads(Executors.newFixedThreadPool(10));
		setFileUploads(Executors.newFixedThreadPool(10));
		
		try 
		{
			socket = new ServerSocket(PORT);
		}
		catch (BindException e)
		{
			logger.info("Ip-Address already in use. Restart program or contact your administrator.");
			setServerIsRunning(false);
		}
		catch (IOException e) 
		{
			e.printStackTrace();
			setServerIsRunning(false);
		}
	}
	
	public void startServer()
	{
		setServerIsRunning(true);
		start();
	}
	
	public void stopServer()
	{
		setServerIsRunning(false);
		fileDownloads.shutdown();
		fileUploads.shutdown();
		
		try {
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run()
	{
		while (isServerIsRunning()) 
		{
			try 
			{
				Socket uploadSocket = socket.accept();
				fileUploads.execute(new TCPSender(uploadSocket));
			} 
			catch (NullPointerException e)
			{
				logger.info("Socket is unavailable.");
				setServerIsRunning(false);
			}
			catch (SocketException e)
			{
				logger.info("Can't receive messages, socket is closed.");
				setServerIsRunning(false);
			}
			catch (IOException e) 
			{
				e.printStackTrace();
				setServerIsRunning(false);
			}
		}
	}
	
	public void dowloadFile(PeerFile peerFile, DownloadFile currentDownload)
	{
		fileDownloads.execute(new TCPReceiver(peerFile, currentDownload));
	}
	
	/**
	 * 
	 * Getters & Setters
	 * 
	 */

	public ServerSocket getSocket() {
		return socket;
	}

	public void setSocket(ServerSocket socket) {
		this.socket = socket;
	}

	public ExecutorService getFileDownloads() {
		return fileDownloads;
	}

	public void setFileDownloads(ExecutorService fileDownloads) {
		this.fileDownloads = fileDownloads;
	}

	public ExecutorService getFileUploads() {
		return fileUploads;
	}

	public void setFileUploads(ExecutorService fileUploads) {
		this.fileUploads = fileUploads;
	}

	public boolean isServerIsRunning() {
		return serverIsRunning;
	}

	public void setServerIsRunning(boolean serverIsRunning) {
		this.serverIsRunning = serverIsRunning;
	}
}
